package view.swinginterface;

import client.request.RequestWorker;
import unit.data.Message;
import view.ClientInterface;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Innokenty Shuvalov
 */
public class SwingInterface extends JFrame implements ClientInterface {

    private LoginForm loginForm;
    private SearchUserForm searchForm;
    private HashMap<Integer, JTextArea> chatTextAreas;

    /**
     * Integer - userId, String - имя параметра в инфе пользователя, String - значение
     */
    private Map<Integer, Map<String, String>> contacts;
    private int currentReceiverId = -1;

    private DefaultListModel listModel = new DefaultListModel();

    private static String DEFAULT_TITLE = "Java Messenger";
    private String myName = "You";

    private static String LOGIN_TEXT = "Login / Register";
    private static String LOGOUT_TEXT = "Logout";
    private boolean loggedIn = false;

    private RequestWorker requestWorker;

    private String[] projective = new String[]{"name"};


    public SwingInterface(RequestWorker requestWorker, String title) {
        init(requestWorker, title);
    }

    public SwingInterface(RequestWorker requestWorker) {
        this(requestWorker, DEFAULT_TITLE);
    }

    private void init(RequestWorker requestWorker, String title) {
        initComponents();

        if (title != null) {
            setTitle(title);
        }

        if (requestWorker != null) {
            this.requestWorker = requestWorker;
        }

        loginForm = new LoginForm(this);

        contactsList.setModel(listModel);
        setEnabledComponents(false);

        //TODO remove sample user list generation
//        contacts = new HashMap<Integer, Map<String, String>>(2);
//        contacts.put(1, new HashMap<String, String>(1));
//        contacts.put(2, new HashMap<String, String>(1));
//        contacts.get(1).put("name", "name11");
//        contacts.get(2).put("name", "name22");
//        setContactList(contacts);

        chatTextAreas = new HashMap<Integer, JTextArea>();

        setVisible(true);
        loginForm.setVisible(true);
    }

    private void init() {
        init(null, null);
    }

    protected RequestWorker getRequestWorker() {
        return requestWorker;
    }

    private void setEnabledContacts(boolean enabled) {
        contactsLabel.setEnabled(enabled);
        contactsList.setEnabled(enabled);
        contactsAddButton.setEnabled(enabled);
        contactsMenu.setEnabled(enabled);
    }

    private void setEnabledChat(boolean enabled) {
        chatTabbedPane.setEnabled(enabled);
        chatInputArea.setEnabled(enabled);
        chatSendButton.setEnabled(enabled);
        chatLabel.setEnabled(enabled);

        if (chatTextAreas != null) {
            for (JTextArea chatTextArea : chatTextAreas.values()) {
                chatTextArea.setEnabled(enabled);
            }
        }
    }

    private void setEnabledComponents(boolean enabled) {
        setEnabledContacts(enabled);
        setEnabledChat(enabled);
    }

    private void loginMenuItemActionPerformed(ActionEvent e) {
        if (loggedIn) {
            init();
            loggedIn = false;
            //TODO send logout
        }
        loginForm.setVisible(true);
    }

    private void quitMenuItemActionPerformed(ActionEvent e) {
        this.dispose();
    }

    private void chatSendButtonActionPerformed(ActionEvent e) {
        String msg = chatInputArea.getText().trim();
        if (!msg.equals("")) {
            requestWorker.sendMessage(msg, currentReceiverId);

            String message = generateMessageView(msg, myName);
            ((JTextArea) chatTabbedPane.getSelectedComponent()).append(message);
            chatInputArea.setText("");
        }
        chatInputArea.grabFocus();
    }

    private String generateMessageView(String msg, String name) {
        return name + ": " + msg + "\n";
    }

    private void contactsListValueChanged(ListSelectionEvent e) {
        UserListItem user = (UserListItem) contactsList.getSelectedValue();
        JTextArea chatWithUser = showChatTab(user.getUserId(), user.getName());
        currentReceiverId = user.getUserId();
        chatTabbedPane.setSelectedComponent(chatWithUser);
        chatInputArea.grabFocus();
    }

    public void showMessage(int senderId, Message msg) {
        showMessage(senderId, msg.getText());
    }

    private void showMessage(int userId, String msg) {
        String name = getExistingUserNameById(userId);
        String message = generateMessageView(msg, name);
        showChatTab(userId, name).append(message);
    }

    private String getExistingUserNameById(int userId) {
        return contacts.get(userId).get("name");
    }

    private JTextArea showChatTab(int userId, String name) {
        JTextArea chatWithUser = chatTextAreas.get(userId);
        if (chatWithUser == null) {
            chatWithUser = new JTextArea();
            chatWithUser.setEditable(false);

            chatTextAreas.put(userId, chatWithUser);
            if (chatTabbedPane.getTabCount() == 0) {
                setEnabledChat(true);
            }
        }
        if (chatTabbedPane.indexOfTab(name) == -1) {
            chatTabbedPane.add(name, chatWithUser);
        }
        return chatWithUser;
    }

    private void chatInputAreaKeyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
            case KeyEvent.VK_ENTER:
                if (e.isShiftDown()) {
                    chatInputArea.append("\n");
                } else {
                    chatSendButtonActionPerformed(null);
                }
                e.consume();
                break;
        }
    }

    public void setUsername(String myName) {
        this.myName = myName;
    }

    /**
     * Integer - userId, String - имя параметра, String - значение
     */
    public void setContactList(Map<Integer, Map<String, String>> contacts) {
        this.contacts = contacts;
        for (Integer uid : contacts.keySet()) {
            listModel.addElement(new UserListItem(contacts.get(uid).get("name"), uid));
        }
        setEnabledContacts(true);
    }

    public void setLoginState(boolean loggedIn) {
        this.loggedIn = loggedIn;
        loginMenuItem.setText(loggedIn ? LOGOUT_TEXT : LOGIN_TEXT);
        if (loggedIn) {
            requestWorker.requestContactsList(projective);
        }
    }

    @Override
    public void addToContactList(int userId) {
        //TODO make smth
        System.out.println("addToContactList(int userId) still in use!!");
    }

    @Override
    public void setSearchResults(Map<String, Integer> searchResults) {
        if (searchForm != null) {
            searchForm.setSearchResults(searchResults);
        }
    }

    private void contactsAddButtonActionPerformed(ActionEvent e) {
        if (searchForm == null) {
            searchForm = new SearchUserForm(this);
        }
        searchForm.setVisible(true);
    }

    private void chatInputAreaKeyTyped(KeyEvent e) {
        // TODO add your code here
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        // Generated using JFormDesigner Evaluation license - iuygi iugiu
        menuBar1 = new JMenuBar();
        mainMenu = new JMenu();
        loginMenuItem = new JMenuItem();
        quitMenuItem = new JMenuItem();
        contactsMenu = new JMenu();
        menuItem3 = new JMenuItem();
        contentPanel = new JPanel();
        contactsPanel = new JPanel();
        contactsLabel = new JLabel();
        scrollPane1 = new JScrollPane();
        contactsList = new JList();
        contactsToolBar = new JToolBar();
        contactsAddButton = new JButton();
        chatPanel = new JPanel();
        chatTabbedPane = new JTabbedPane();
        chatLabel = new JLabel();
        chatSendButton = new JButton();
        scrollPane2 = new JScrollPane();
        chatInputArea = new JTextArea();

        //======== this ========
        setMinimumSize(new Dimension(515, 400));
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        Container contentPane = getContentPane();

        //======== menuBar1 ========
        {

            //======== mainMenu ========
            {
                mainMenu.setText("Menu");

                //---- loginMenuItem ----
                loginMenuItem.setText("Login / Register");
                loginMenuItem.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        loginMenuItemActionPerformed(e);
                    }
                });
                mainMenu.add(loginMenuItem);

                //---- quitMenuItem ----
                quitMenuItem.setText("Quit");
                quitMenuItem.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        quitMenuItemActionPerformed(e);
                    }
                });
                mainMenu.add(quitMenuItem);
            }
            menuBar1.add(mainMenu);

            //======== contactsMenu ========
            {
                contactsMenu.setText("Contacts");

                //---- menuItem3 ----
                menuItem3.setText("Add");
                menuItem3.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        contactsAddButtonActionPerformed(e);
                    }
                });
                contactsMenu.add(menuItem3);
            }
            menuBar1.add(contactsMenu);
        }
        setJMenuBar(menuBar1);

        //======== contentPanel ========
        {
            contentPanel.setMinimumSize(new Dimension(500, 340));

            //======== contactsPanel ========
            {
                contactsPanel.setEnabled(false);
                contactsPanel.setFocusable(false);

                //---- contactsLabel ----
                contactsLabel.setText("\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u044b");
                contactsLabel.setFont(new Font("Tahoma", Font.BOLD, 14));
                contactsLabel.setLabelFor(contactsList);

                //======== scrollPane1 ========
                {

                    //---- contactsList ----
                    contactsList.setForeground(new Color(0, 51, 204));
                    contactsList.setFont(new Font("Tahoma", contactsList.getFont().getStyle(), contactsList.getFont().getSize() + 1));
                    contactsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                    contactsList.addListSelectionListener(new ListSelectionListener() {
                        @Override
                        public void valueChanged(ListSelectionEvent e) {
                            contactsListValueChanged(e);
                        }
                    });
                    scrollPane1.setViewportView(contactsList);
                }

                //======== contactsToolBar ========
                {
                    contactsToolBar.setFloatable(false);
                    contactsToolBar.setMinimumSize(new Dimension(100, 29));

                    //---- contactsAddButton ----
                    contactsAddButton.setText("Add");
                    contactsAddButton.setFont(contactsAddButton.getFont().deriveFont(contactsAddButton.getFont().getSize() + 1f));
                    contactsAddButton.setPreferredSize(new Dimension(83, 30));
                    contactsAddButton.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            contactsAddButtonActionPerformed(e);
                        }
                    });
                    contactsToolBar.add(contactsAddButton);
                }

                GroupLayout contactsPanelLayout = new GroupLayout(contactsPanel);
                contactsPanel.setLayout(contactsPanelLayout);
                contactsPanelLayout.setHorizontalGroup(
                        contactsPanelLayout.createParallelGroup()
                                .addGroup(contactsPanelLayout.createSequentialGroup()
                                        .addComponent(contactsLabel, GroupLayout.DEFAULT_SIZE, 130, Short.MAX_VALUE)
                                        .addContainerGap())
                                .addComponent(contactsToolBar, GroupLayout.DEFAULT_SIZE, 136, Short.MAX_VALUE)
                                .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 136, GroupLayout.PREFERRED_SIZE)
                );
                contactsPanelLayout.setVerticalGroup(
                        contactsPanelLayout.createParallelGroup()
                                .addGroup(contactsPanelLayout.createSequentialGroup()
                                        .addComponent(contactsLabel)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(scrollPane1, GroupLayout.DEFAULT_SIZE, 386, Short.MAX_VALUE)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(contactsToolBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
                );
            }

            //======== chatPanel ========
            {

                //---- chatLabel ----
                chatLabel.setText("\u0427\u0430\u0442");
                chatLabel.setFont(chatLabel.getFont().deriveFont(chatLabel.getFont().getStyle() | Font.BOLD, chatLabel.getFont().getSize() + 3f));

                //---- chatSendButton ----
                chatSendButton.setText("Send");
                chatSendButton.setFont(chatSendButton.getFont().deriveFont(chatSendButton.getFont().getSize() + 3f));
                chatSendButton.setToolTipText("Enter: send, Shft + Enter: new line");
                chatSendButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        chatSendButtonActionPerformed(e);
                    }
                });

                //======== scrollPane2 ========
                {

                    //---- chatInputArea ----
                    chatInputArea.setFont(chatInputArea.getFont().deriveFont(chatInputArea.getFont().getSize() + 1f));
                    chatInputArea.addKeyListener(new KeyAdapter() {
                        @Override
                        public void keyPressed(KeyEvent e) {
                            chatInputAreaKeyPressed(e);
                        }
                    });
                    scrollPane2.setViewportView(chatInputArea);
                }

                GroupLayout chatPanelLayout = new GroupLayout(chatPanel);
                chatPanel.setLayout(chatPanelLayout);
                chatPanelLayout.setHorizontalGroup(
                        chatPanelLayout.createParallelGroup()
                                .addGroup(chatPanelLayout.createSequentialGroup()
                                        .addGap(6, 6, 6)
                                        .addComponent(chatLabel, GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE))
                                .addGroup(GroupLayout.Alignment.TRAILING, chatPanelLayout.createSequentialGroup()
                                        .addComponent(scrollPane2, GroupLayout.DEFAULT_SIZE, 334, Short.MAX_VALUE)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(chatSendButton, GroupLayout.PREFERRED_SIZE, 73, GroupLayout.PREFERRED_SIZE))
                                .addComponent(chatTabbedPane, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 413, Short.MAX_VALUE)
                );
                chatPanelLayout.setVerticalGroup(
                        chatPanelLayout.createParallelGroup()
                                .addGroup(chatPanelLayout.createSequentialGroup()
                                        .addComponent(chatLabel)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(chatTabbedPane, GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(chatPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING, false)
                                                .addComponent(chatSendButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                .addComponent(scrollPane2, GroupLayout.DEFAULT_SIZE, 46, Short.MAX_VALUE)))
                );
            }

            GroupLayout contentPanelLayout = new GroupLayout(contentPanel);
            contentPanel.setLayout(contentPanelLayout);
            contentPanelLayout.setHorizontalGroup(
                    contentPanelLayout.createParallelGroup()
                            .addGroup(GroupLayout.Alignment.TRAILING, contentPanelLayout.createSequentialGroup()
                                    .addContainerGap()
                                    .addComponent(chatPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addGap(18, 18, 18)
                                    .addComponent(contactsPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                                    .addContainerGap())
            );
            contentPanelLayout.setVerticalGroup(
                    contentPanelLayout.createParallelGroup()
                            .addGroup(GroupLayout.Alignment.TRAILING, contentPanelLayout.createSequentialGroup()
                                    .addContainerGap()
                                    .addGroup(contentPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                                            .addComponent(chatPanel, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .addComponent(contactsPanel, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                    .addContainerGap())
            );
        }

        GroupLayout contentPaneLayout = new GroupLayout(contentPane);
        contentPane.setLayout(contentPaneLayout);
        contentPaneLayout.setHorizontalGroup(
                contentPaneLayout.createParallelGroup()
                        .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        contentPaneLayout.setVerticalGroup(
                contentPaneLayout.createParallelGroup()
                        .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        pack();
        setLocationRelativeTo(getOwner());
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    // Generated using JFormDesigner Evaluation license - iuygi iugiu
    private JMenuBar menuBar1;
    private JMenu mainMenu;
    private JMenuItem loginMenuItem;
    private JMenuItem quitMenuItem;
    private JMenu contactsMenu;
    private JMenuItem menuItem3;
    private JPanel contentPanel;
    private JPanel contactsPanel;
    private JLabel contactsLabel;
    private JScrollPane scrollPane1;
    private JList contactsList;
    private JToolBar contactsToolBar;
    private JButton contactsAddButton;
    private JPanel chatPanel;
    private JTabbedPane chatTabbedPane;
    private JLabel chatLabel;
    private JButton chatSendButton;
    private JScrollPane scrollPane2;
    private JTextArea chatInputArea;
    // JFormDesigner - End of variables declaration  //GEN-END:variables

    public static void main(String[] args) {
        SwingInterface inter = new SwingInterface(null);
    }
}